package com.paradogs.gs.misc;

import com.paradogs.framework.annotations.serverHandler.PRMapping;
import com.paradogs.gs.modules.GameObject;
import com.paradogs.gs.utils.PlayerUtils;
import org.springframework.cglib.proxy.*;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Method;

/**
 * @author: yumi
 * @date: 2024/2/26  17:48
 * @Description: 通知组件代理
 *
    // 创建 NoticeManager 代理对象
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(NoticeManager.class);
    enhancer.setCallback(new NoticeManagerProxy(id));
    this.noticeManager = (NoticeManager) enhancer.create();
 */
public class _NetMgrProxy implements MethodInterceptor, IManager {

    private GameObject gameObject;

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        PRMapping annotation = AnnotationUtils.findAnnotation(method, PRMapping.class);
        // 没有注解则为普通方法
        if (annotation == null) {
            return proxy.invokeSuper(obj, args); // 执行原先方法，必须用 proxy 调用，否则会重复进入代理造成死循环
        }
        // 代理映射接口
//        _NetMgr _netMgr = (_NetMgr) obj;
        String noticeRoute = annotation.value(); // 路由信息
        // 通知客户端
        PlayerUtils.notifyPlayer(((_NetMgrProxy) obj).gameObject.getId(), noticeRoute, args[0]);
        return obj;
    }

    /** 创建 _NetMgr 接口的动态代理实例 !!! 还需要调用 loadFromDB() 初始化 gameObject 用于获得 uid */
    public static _NetMgr buildNetMgr() {
        // 创建 _NetMgr 代理对象
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(_NetMgrProxy.class);
        enhancer.setInterfaces(new Class[]{ _NetMgr.class });
        enhancer.setCallbacks(new Callback[]{ new _NetMgrProxy(), NoOp.INSTANCE });
        // 解决 module java.base does not open java.lang to unnamed module @730d2164
        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                // 判断是否是Object类中定义的hashCode方法（更准确的判断）
                if (method.getDeclaringClass().equals(Object.class)
                        && "hashCode".equals(method.getName())) {
                    return 1;
                }
                return 0;
            }
        });
        _NetMgr mgr = (_NetMgr) enhancer.create();
        return mgr;
    }

    @Override
    public String toString() {
        return "_NetMgrProxy{" +
                "gameObject=" + gameObject.getId() +
                '}';
    }

    @Override
    public void loadData(GameObject gameObject) {
        this.gameObject = gameObject;
    }

}
